Typical HAL TIM use cases for migration

This section provides information about typical HAL TIM use cases for migration.

Specific TIM Concept

HAL1 vs HAL2 Initialization

Functionality

HAL1

HAL2

Initialization

  • In contrast, HAL2 simplifies this process by replacing all these individual initialization functions with a single function followed by a configuration function:

    • HAL_TIM_Init(&htim, HAL_TIMi)

    • HAL_TIM_SetConfig(&htim, &p_config)

    Important

    In HAL1, the functions HAL_TIM_OnePulse_Init, HAL_TIM_Encoder_Init, and HAL_TIMEx_HallSensor_Init include additional configurations beyond the basic setup. Therefore, in HAL2, in addition to HAL_TIM_Init and HAL_TIM_SetConfig, other functions must be called to achieve the same behavior as in HAL1.


HAL1 vs HAL2 Deinitialization

Functionality

HAL1

HAL2

Deinitialization

  • Similarly to Initialization, HAL1 requires individual deinitialization functions for each process:

    • HAL_TIM_Base_DeInit(&htim) for the base timer.

    • HAL_TIM_OC_DeInit(&htim) for the output compare.

    • HAL_TIM_PWM_DeInit(&htim) for the PWM.

    • HAL_TIM_IC_DeInit(&htim) for the input capture.

    • HAL_TIM_OnePulse_DeInit(&htim) for the one-pulse mode.

    • HAL_TIM_Encoder_DeInit(&htim) for the encoder interface.

    • HAL_TIMEx_HallSensor_DeInit(&htim) for the Hall sensor.

  • In HAL2, the deinitialization process is simplified with a single function for all processes:

    • Deinitialize the timer using HAL_TIM_DeInit(&htim).


HAL1 vs HAL2 Start and Stop

Functionality

HAL1

HAL2

Start and Stop

  • In HAL1, each process has its own function for start and stop:

    • HAL_TIM_Base_Start/IT/DMA

    • HAL_TIM_Base_Stop/IT/DMA

    • HAL_TIM_OC_Start/IT/DMA

    • HAL_TIM_OC_Stop/IT/DMA

    • HAL_TIMEx_OCN_Start/IT/DMA

    • HAL_TIMEx_OCN_Stop/IT/DMA

    • HAL_TIM_PWM_Start/IT/DMA

    • HAL_TIM_PWM_Stop/IT/DMA

    • HAL_TIMEx_PWMN_Start/IT/DMA

    • HAL_TIMEx_PWMN_Stop/IT/DMA

    • HAL_TIM_IC_Start/IT/DMA

    • HAL_TIM_IC_Stop(&htim)

    • HAL_TIM_OnePulse_Start/IT

    • HAL_TIM_OnePulse_Stop/IT

    • HAL_TIMEx_OnePulse_Start/IT

    • HAL_TIMEx_OnePulse_Stop/IT

    • HAL_TIM_Encoder_Start/IT/DMA

    • HAL_TIM_Encoder_Stop/IT/DMA

    • HAL_TIMEx_HallSensor_Start/IT/DMA

    • HAL_TIMEx_HallSensor_Stop/IT/DMA

  • In HAL2, depending on the function to be performed by the timer and depending on the way the channel is used, either output or input, there are specific functions to use:

    • If the process is for simple Time base:

      • HAL_TIM_Start/IT/DMA/IT_Opt/DMA_Opt

      • HAL_TIM_Stop/IT/DMA

    • If the process is for an output compare, we call upon the function that allows starting the channel process in output mode:

      • HAL_TIM_OC_StartChannel/IT/DMA/DMA_Opt

      • HAL_TIM_Start

    • If the process is for an input capture, we call upon the function that allows starting the channel process in input mode:

      • HAL_TIM_IC_StartChannel/IT/DMA/DMA_Opt

      • HAL_TIM_Start

    Note

    IT_Opt and DMA_Opt are new HAL2 features that allow optional interrupt and DMA configuration. For example, DMA can be configured without generating an interrupt, and interrupt mode can be configured while selecting the interrupt source.


HAL1 vs HAL2 Channel Configuration

Functionality

HAL1

HAL2

Channel Configuration

  • In HAL1, each process has its own function for channel configuration:

    • HAL_TIM_OC_ConfigChannel

    • HAL_TIM_PWM_ConfigChannel

    • HAL_TIM_IC_ConfigChannel

    • HAL_TIM_OnePulse_ConfigChannel

  • In HAL2, depending on the way the channel is used, either output or input, there are specific functions to use:

    • If the channel is used for output:

      • HAL_TIM_OC_SetConfigChannel

      • HAL_TIM_OC_SetConfigCompareUnit

    • If the channel is used for input:

      • HAL_TIM_IC_SetConfigChannel

      • HAL_TIM_IC_SetConfigCaptureUnit


TIM use cases

Use case: Time base in interrupt mode

HAL1

HAL2

Start TIMx in interrupt mode

  • The function HAL_TIM_Base_Start_IT() is used to enable:

    • The TIMx peripheral.

    • The update event interrupt.

TIMx IRQ handler

  • Inside the TIMx interrupt handler, the user calls the global IRQ handler of the TIM driver HAL_TIM_IRQHandler() to handle the update interrupt request.

Callback function

  • The function HAL_TIM_PeriodElapsedCallback() is called when the period elapses.

Start TIMx in interrupt mode

  • The function HAL_TIM_Start_IT() is used to enable:

    • The TIMx peripheral.

    • The update event interrupt.

TIMx IRQ handler

  • Inside the TIMx interrupt handler, the user can call either:

    • The global IRQ handler HAL_TIM_IRQHandler() to handle the TIMx interrupt request, or

    • The single process IRQ handler for specific interrupt events in this case HAL_TIM_UPD_IRQHandler().

Callback function

  • The function HAL_TIM_UpdateCallback() is called when the period elapses.

Sequence diagram

Timer as basic counter

@startuml
' To add a number by line
'autonumber

title "Timer as basic counter HAL 1"

' Fix order of each column
participant "User Application" as App
participant "HAL TIM" as HAL_TIM
participant "MSP" as MSP
participant "IT" as IT

group Initialization
App -[hidden]>HAL_TIM
end

group Start TIMx in IT mode
App -> HAL_TIM: <b><font color=blue>HAL_TIM_Base_Start_IT</b>()
HAL_TIM -> HAL_TIM: Enable UPDATE interrupt\nEnable TIMx counter
IT <[#red]-] : <font color=red><b>TIMx IRQ
IT -> HAL_TIM: TIMx IRQ
HAL_TIM -> HAL_TIM: HAL_TIM_IRQHandler()
HAL_TIM -> HAL_TIM: Clear flag
HAL_TIM -> App: <b><font color=green>HAL_TIM_PeriodElapsedCallback</b>()
end
@enduml

Code snippet

HAL1

HAL2

/* Declaration of the tim handle */
TIM_HandleTypeDef htim2;

/* Ensure that all required peripherals
(TIM, GPIO, NVIC, etc.) are configured properly
before starting the timer.*/
.............

/* Start the timer TIMx in interrupt mode */
HAL_TIM_Base_Start_IT(&htim2);

/* User must call the Interrupt Handler
  functions in TIMx global interrupt */

void TIM2_IRQHandler(void)
{
    /* Code to execute at each interrupt */
    HAL_TIM_IRQHandler(&htim2);
}

/* Call the callback function */

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
        /* Code to execute at each interrupt
          For example, toggle an LED */
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
}
/* Declaration of the tim handle */
hal_tim_handle_t htim2;

/* Ensure that all required peripherals
(TIM, GPIO, NVIC, etc.) are configured properly
before starting the timer.*/
     .............

/* Start the timer TIMx in interrupt mode */
HAL_TIM_Start_IT(&htim2);

/* User must call the Interrupt Handler
 functions in TIM2 global interrupt */

void TIM2_IRQHandler(void)
{
    /* Code to execute at each interrupt */
    HAL_TIM_IRQHandler(&htim2);
}

/* Call the callback function */

void HAL_TIM_UpdateCallback(hal_tim_handle_t *htim)
{
    /* Code to execute at each interrupt
       For example, toggle an LED */
    HAL_GPIO_TogglePin(HAL_GPIOA, HAL_GPIO_PIN_5);
}

Key changes

  1. The time base start API is renamed from HAL_TIM_Base_Start_IT() to HAL_TIM_Start_IT().

  2. The update callback is renamed from HAL_TIM_PeriodElapsedCallback() to HAL_TIM_UpdateCallback().

  3. HAL2 provides a dedicated update IRQ handler HAL_TIM_UPD_IRQHandler() in addition to the global handler HAL_TIM_IRQHandler().

Use case: PWM output in interrupt mode

HAL1

HAL2

Channel configuration

  • To initialize the TIM PWM channels according to the specified parameters, call:

    • HAL_TIM_PWM_ConfigChannel.

Start PWM signal in interrupt mode

  • The function HAL_TIM_PWM_Start_IT(&htim, TIM_CHANNEL_x) is used to enable:

    • The TIMx peripheral.

    • The selected channel x.

    • The capture compare x interrupt.

TIMx IRQ handler

  • Inside the interrupt handler for TIMx, the user calls the global IRQ handler of the TIM driver HAL_TIM_IRQHandler() to handle the capture compare x interrupt request.

Callback function

  • The function HAL_TIM_PWM_PulseFinishedCallback() is called when the PWM pulse is finished.

Channel configuration

  • Replace the channel configuration by the following sequence:

    • HAL_TIM_OC_SetConfigChannel

    • HAL_TIM_OC_SetConfigCompareUnit

Start PWM signal in interrupt mode

  • The function HAL_TIM_OC_StartChannel_IT(&htim, TIM_CHANNEL_x) is used to enable:

    1. The selected channel x.

    2. The capture compare x interrupt.

  • The function HAL_TIM_Start() is used to enable and start the TIMx.

TIMx IRQ handler

  • Inside the interrupt handler for TIMx, the user can call either:

    • The global IRQ handler HAL_TIM_IRQHandler() to handle the capture compare x interrupt request, or

    • The single process IRQ handler for specific interrupt events in this case HAL_TIM_CC_IRQHandler().

Callback function

  • The function HAL_TIM_CompareMatchCallback() is called when the output compare event occurs.

Important

When using PWM with DMA, it is mandatory to call the function HAL_TIM_OC_EnableChannelComparePreload.

Sequence diagram

PWM output

@startuml
skinparam maxMessageSize 440
' To add a number by line
'autonumber

title "PWM Output in HAL 1"

' Fix order of each column
participant "User Application" as App
participant "HAL TIM" as Driver

participant "IT" as IT

group Initialization and configuration of TIMx
App -[hidden]>Driver
end


group Configuration of channel


App -> Driver : \n<b><font color=purple>HAL_TIM_PWM_ConfigChannel</b>(channel = <font color=blue>HAL_TIM_CHANNEL_<b>x</b>,\n(TIM_OC_InitTypeDef) {\n.OCPolarity = TIM_OCPOLARITY_HIGH,\n.OCIdleState = TIM_OCIDLESTATE_RESET,\n.OCMode = TIM_OCMODE_PWM1,\n.Pulse = PULSE1_VALUE})
Driver --> App : HAL_O

end

group Start TIMx in IT mode

App -> Driver : <b><font color=blue>HAL_TIM_PWM_Start_IT</b>(&htim, HAL_TIM_CHANNEL_<b>x</b>)
Driver --> App : HAL_OK
Driver->Driver : Enable capture compare interrupt\nEnable TIMx counter
Driver --> App : HAL_OK
IT <[#red]-] : <font color=red><b>TIMx IRQ
IT -> Driver : HAL_TIM_IRQHandler()
Driver -> Driver : Clear flag
Driver -> App: <b><font color=green>HAL_TIM_PWM_PulseFinishedCallback</b>()
App --> Driver
Driver --> IT

end
@enduml

Code snippet

HAL1

HAL2

/* Declaration of tim handle */
TIM_HandleTypeDef htim3;

/* Ensure that all required peripherals
(TIM(timer, channel), GPIO, NVIC, etc.) are configured properly
before starting PWM output.*/
.............

/* Start the PWM output in interrupt mode */
HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_2);

/* User must call the Interrupt Handler
  functions in TIM3 global interrupt */

void TIM3_IRQHandler(void)
{
    /* Code to execute at each interrupt */
    HAL_TIM_IRQHandler(&htim3);
}

/* Call the callback function */

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
        /* Code to execute at each compare match interrupt
          For example, toggle an LED */
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
}
 /* Declaration of the tim handle */
 hal_tim_handle_t htim3;

 /* Ensure that all required peripherals
 (TIM(timer, channel), GPIO, NVIC, etc.) are configured properly
 before starting PWM output.*/
      .............

/* Start a timer's output channel in interrupt mode. */
 HAL_TIM_OC_StartChannel_IT(&htim3, HAL_TIM_CHANNEL_2);

 /* Start the timer */
 HAL_TIM_Start(&htim3);

 /* User must call the Interrupt Handler
  functions in TIM2 global interrupt */

 void TIM2_IRQHandler(void)
 {
     /* Code to execute at each interrupt */
     HAL_TIM_IRQHandler(&htim3);
 }

 /* Call the callback function */

 void HAL_TIM_CompareMatchCallback(hal_tim_handle_t *htim,
                          hal_tim_channel_t channel);
 {
     /* Code to execute at each interrupt
        For example, toggle an LED */
     HAL_GPIO_TogglePin(HAL_GPIOA, HAL_GPIO_PIN_5);
 }

Key changes

  1. PWM configuration APIs are replaced by the output compare configuration sequence in HAL2.

  2. Channel start in interrupt mode uses HAL_TIM_OC_StartChannel_IT() and timer start uses HAL_TIM_Start().

  3. The PWM pulse finished callback is replaced by the output compare match callback HAL_TIM_CompareMatchCallback().

Related examples in HAL2

For more details, refer to the complete example under the firmware directory.

Example name

Brief

pwm_output

How to configure the TIM peripheral in PWM (Pulse Width Modulation) mode. The PWM waveforms generated by the timer channels can be displayed using an oscilloscope.


Use case: Input capture in interrupt mode

HAL1

HAL2

Start input capture in interrupt mode

  • The function HAL_TIM_IC_Start_IT(&htim, TIM_CHANNEL_x) is used to enable:

    • The TIMx peripheral.

    • The selected channel x.

    • The capture compare x interrupt.

TIMx IRQ handler

  • Inside the interrupt handler for TIMx, the user calls the global IRQ handler of the TIM driver HAL_TIM_IRQHandler() to handle the capture compare x interrupt request.

Callback function

  • The function HAL_TIM_IC_CaptureCallback() is called when the input capture occurs.

Start input capture in interrupt mode

  • The function HAL_TIM_IC_StartChannel_IT(&htim, TIM_CHANNEL_x) is used to enable:

    1. The selected channel x.

    2. The capture compare x interrupt.

  • The function HAL_TIM_Start() is used to enable and start the TIMx.

TIMx IRQ handler

  • Inside the interrupt handler for TIMx, the user can call either:

    • The global IRQ handler HAL_TIM_IRQHandler() to handle the capture compare x interrupt request, or

    • The single process IRQ handler for specific interrupt events in this case HAL_TIM_CC_IRQHandler().

Callback function

  • The function HAL_TIM_InputCaptureCallback() is called when the input capture event occurs.

Sequence diagram

Input capture

@startuml
skinparam maxMessageSize 440
' To add a number by line
'autonumber

title "Input Capture in HAL 1"

' Fix order of each column
participant "User Application" as App
participant "HAL TIM" as Driver

participant "IT" as IT

group Initialization and configuration of TIMx
App -[hidden]>Driver
end


group Configuration of channel


App -> Driver : \n<b><font color=blue>HAL_TIM_IC_ConfigChannel</b>(channel = <font color=blue>HAL_TIM_CHANNEL_<b>x</b>,\n(TIM_IC_InitTypeDef) {\n.ICPolarity = TIM_ICPOLARITY_RISING,\n.ICSelection = TIM_ICSELECTION_DIRECTTI,\n.ICPrescaler = TIM_ICPSC_DIV1,\n.ICFilter = 0})
Driver --> App : HAL_OK

end

group Start TIMx in IT mode

App -> Driver : HAL_TIM_IC_Start_IT(&htim, HAL_TIM_CHANNEL_<b>x</b>)
Driver --> App : HAL_OK
Driver->Driver : Enable capture compare interrupt\nEnable TIMx counter
Driver --> App : HAL_OK
IT <[#red]-] : <font color=red><b>TIMx IRQ
IT -> Driver : HAL_TIM_IRQHandler()
Driver -> Driver : Clear flag
Driver -> App: HAL_TIM_IC_CaptureCallback()
App --> Driver
Driver --> IT

end
@enduml

Code snippet

HAL1

HAL2

/* Declaration of tim handle */
TIM_HandleTypeDef htim3;

/* Ensure that all required peripherals
(TIM(timer, channel), GPIO, NVIC, etc.) are configured properly
before starting the input capture.*/
.............

/* Start the Input Capture in interrupt mode */
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);

/* User must call the Interrupt Handler
  functions in TIM3 global interrupt */

void TIM3_IRQHandler(void)
{
    /* Code to execute at each interrupt */
    HAL_TIM_IRQHandler(&htim3);
}

/* Call the callback function */

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
      /* Get the Input Capture value */
      uwIC2Value = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_2);
}
 /* Declaration of the tim handle */
 hal_tim_handle_t htim3;

 /* Ensure that all required peripherals
 (TIM(timer, channel), GPIO, NVIC, etc.) are configured properly
 before starting the input capture.*/
      .............

/* Start a timer's output channel in interrupt mode. */
 HAL_TIM_IC_StartChannel_IT(&htim3, HAL_TIM_CHANNEL_2);

 /* Start the timer */
 HAL_TIM_Start(&htim3);

 /* User must call the Interrupt Handler
  functions in TIM3 global interrupt */

 void TIM3_IRQHandler(void)
 {
     /* Code to execute at each interrupt */
     HAL_TIM_IRQHandler(&htim3);
 }

 /* Call the callback function */

 void HAL_TIM_InputCaptureCallback(hal_tim_handle_t *htim,
                          hal_tim_channel_t channel);
 {
   /* Get the Input Capture value */
     uwIC2Value = HAL_TIM_IC_ReadChannelCapturedValue(&htim3, HAL_TIM_CHANNEL_2)
 }

Key changes

  1. Input capture start API changes from HAL_TIM_IC_Start_IT() to HAL_TIM_IC_StartChannel_IT() and requires HAL_TIM_Start().

  2. The callback is renamed from HAL_TIM_IC_CaptureCallback() to HAL_TIM_InputCaptureCallback().

Related examples in HAL2

For more details, refer to the complete example under the firmware directory.

Example name

Brief

input_capture

How to configure the TIM peripheral in input capture mode to measure the frequency of an external signal.


Use case: Encoder interface in interrupt mode

HAL1

HAL2

Initialization and configuration

  • The function HAL_TIM_Encoder_Init(&htim1, &sConfig) is used to configure:

    • The TIMx peripheral.

    • Encoder mode.

    • The TIMx CH1 and CH2.

Start encoder interface in interrupt mode

  • The function HAL_TIM_Encoder_Start_IT is used to start the TIM Encoder Interface in interrupt mode.

TIMx IRQ handler

  • Inside the interrupt handler for TIMx, the user calls the global IRQ handler of the TIM driver HAL_TIM_IRQHandler() to handle the capture compare x interrupt request.

Callback function

  • The function HAL_TIM_IC_CaptureCallback() is called when the input capture occurs.

Initialization and configuration

  • The functions HAL_TIM_Init and HAL_TIM_SetConfig are used to configure:

    • The TIMx peripheral.

    • Encoder mode.

  • The functions HAL_TIM_IC_SetConfigChannel and HAL_TIM_IC_SetConfigCaptureUnit are used to configure TIMx channels (CH1 and CH2).

Start encoder interface in interrupt mode

  • The functions HAL_TIM_IC_StartChannel_IT and HAL_TIM_Start() are used to start the encoder interface in interrupt mode.

TIMx IRQ handler

  • Inside the interrupt handler for TIMx, the user can call either:

    • The global IRQ handler HAL_TIM_IRQHandler() to handle the capture compare x interrupt request, or

    • The single process IRQ handler for specific interrupt events in this case HAL_TIM_CC_IRQHandler().

Callback function

  • The function HAL_TIM_InputCaptureCallback() is called when the input capture event occurs.

Sequence diagram

Encoder interface

@startuml
title "Encoder Mode in HAL 1"

participant "User Application" as App
participant "HAL TIM" as Driver
participant "MSP" as MSP

group Initialization and Configuration
    App -> Driver: <b><font color=purple>HAL_TIM_Encoder_Init</b>(&(TIM_Encoder_InitTypeDef){\nSet Instance (TIMx)\nSet Init structure\nEncoderMode = TIM_ENCODERMODE_TI12,\nIC1Polarity = TIM_ICPOLARITY_RISING,\nIC1Selection = TIM_ICSELECTION_DIRECTTI,\nIC1Prescaler = TIM_ICPSC_DIV1,\nIC1Filter = 0,\nIC2Polarity = TIM_ICPOLARITY_RISING,\nIC2Selection = TIM_ICSELECTION_DIRECTTI,\nIC2Prescaler = TIM_ICPSC_DIV1,\nIC2Filter = 0})
    Driver -> MSP: HAL_TIM_ENCODER_MspInit()
    MSP -> Driver: Enable TIMx clock\nCH1, CH2 GPIO AF config
end

group Start TIMx in IT Mode
    App -> Driver: <b><font color=green>HAL_TIM_Encoder_Start_IT</b>(TIM_CHANNEL_ALL)
    Driver->Driver : Enable capture compare interrupt\nEnable TIMx counter
    Driver --> App : HAL_OK
    IT <[#red]-] : <font color=red><b>TIMx IRQ
    IT -> Driver : HAL_TIM_IRQHandler()
    Driver -> Driver : Clear flag
    Driver -> App: HAL_TIM_IC_CaptureCallback()
    App --> Driver
    Driver --> IT
    end
@enduml

Code snippet

HAL1

HAL2

/* Declaration of tim handle */
TIM_HandleTypeDef htim3;

/* Ensure that all required peripherals
(TIM(timer, channel), GPIO, NVIC, etc.) are configured properly
before starting encoder mode.*/
.............

/* Start the encoder mode in interrupt */
HAL_TIM_Encoder_Start_IT(&htim3, TIM_CHANNEL_ALL);

/* User must call the Interrupt Handler
  functions in TIM3 global interrupt */

void TIM3_IRQHandler(void)
{
    /* Code to execute at each interrupt */
    HAL_TIM_IRQHandler(&htim3);
}

/* Call the callback function */


void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
      /* Get the Input Capture value */
      uwIC2Value = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_2);
}
 /* Declaration of the tim handle */
 hal_tim_handle_t htim3;

 /* Ensure that all required peripherals
 (TIM(timer, channel), GPIO, NVIC, etc.) are configured properly
 before starting encoder mode.*/
      .............

/* Start the encoder mode in interrupt */
 HAL_TIM_IC_StartChannel_IT(&htim3, HAL_TIM_CHANNEL_1);
 HAL_TIM_IC_StartChannel_IT(&htim3, HAL_TIM_CHANNEL_2);
 HAL_TIM_Start(&htim3);

 /* User must call the Interrupt Handler
  functions in TIM2 global interrupt */

 void TIM3_IRQHandler(void)
 {
     /* Code to execute at each interrupt */
     HAL_TIM_IRQHandler(&htim3);
 }

 /* Call the callback function */

 void HAL_TIM_InputCaptureCallback(hal_tim_handle_t *htim,
                          hal_tim_channel_t channel);
 {
     /* Get the Input Capture value */
     uwIC2Value = HAL_TIM_IC_ReadChannelCapturedValue(&htim3, HAL_TIM_CHANNEL_2)
 }

Key changes

  1. Encoder initialization is unified in HAL2 using HAL_TIM_Init() + HAL_TIM_SetConfig() and channel configuration uses input-capture configuration APIs.

  2. Encoder start in interrupt mode is performed with per-channel start APIs and requires HAL_TIM_Start().


Use case: External trigger synchro

This example shows how to synchronize TIM peripherals in cascade mode with an external trigger. In this example three timers are used:

  • TIM1 is slave for an external trigger and master for TIM2.

  • TIM2 is slave for TIM1.

HAL1

HAL2

Initialize and configure timers

  • After initialization and basic configuration for TIMx, configure TIMx as master or slave timer using the following functions:

    • HAL_TIM_SlaveConfigSynchro to configure slave mode.

    • HAL_TIMEx_MasterConfigSynchronization to configure master mode.

    • HAL_TIM_OC_ConfigChannel to configure the output channel.

Start timers

  • HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_2) is used to capture the external trigger.

  • HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1) is used as trigger output for TIM2.

  • HAL_TIM_OC_Start(&htim2, TIM_CHANNEL_1) is used to generate a signal.

Initialize and configure timers

Start timers

  • HAL_TIM_IC_StartChannel(&htim1, HAL_TIM_CHANNEL_2) is used to capture the external trigger.

  • HAL_TIM_OC_StartChannel(&htim1, HAL_TIM_CHANNEL_1) is used as trigger output for TIM2.

  • HAL_TIM_OC_StartChannel(&htim2, HAL_TIM_CHANNEL_1) is used to generate a signal.

  • HAL_TIM_Start(&htim1) is used to start TIM1.

  • HAL_TIM_Start(&htim2) is used to start TIM2.

Sequence diagram

External trigger synchro

@startuml
skinparam maxMessageSize 450
' To add a number by line
'autonumber

title "ExtTriggerSynchro in Cube 2"


' Fix order of each column
participant "User Application" as App
participant "HAL TIM" as Driver

group Initialization
App -[hidden]>Driver
App -> Driver : Configure TIM1, TIM2 time base
Driver -> App : HAL_OK
end

group Configuration of master and salve timer
App -> Driver : Configure TIM1 as slave for external trigger  and master for TIM2.
Driver --> App : HAL_OK
App -> Driver : Configure TIM2 as slave for TIM1.
Driver --> App : HAL_OK

App -> App : CH1, CH2 GPIO AF config

end

group Start TIM1 and TIM2

App -> Driver : <b>HAL_TIM_IC_Start</b>(&htim<b><font color=red>1</b>, TIM_CHANNEL_2)
App -> Driver : <b>HAL_TIM_OC_Start</b>(&htim<b><font color=red>1</b>, TIM_CHANNEL_1)
Driver --> App : HAL_OK

App -> Driver : <b>HAL_TIM_OC_Start</b>(&htim<b><font color=green>2</b>, TIM_CHANNEL_1)
Driver --> App : HAL_OK
end
@enduml

Code snippet

HAL1

HAL2

/* Declaration of tim handle */
TIM_HandleTypeDef htim1, htim2;
TIM_SlaveConfigTypeDef sSlaveConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};

/* Ensure that all required peripherals
(TIM(basic configurations),
 GPIO etc.) are configured properly
 before starting the timers using STM32CubeMX2 */
.............

 /* Configure the slave mode for TIM1*/
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;
  sSlaveConfig.InputTrigger = TIM_TS_TI2FP2;
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;
  sSlaveConfig.TriggerFilter = 0;
  HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig);

  /* Configure the master mode for TIM1*/
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_ENABLE;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_ENABLE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);

  /* Configure the output channel generated by TIM1 to trigger TIM2*/
  sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);

  /* Configure the slave mode  for TIM2*/
  SlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;
  SlaveConfig.InputTrigger = TIM_TS_ITR2;
  HAL_TIM_SlaveConfigSynchro(&htim2, &sSlaveConfig)

  /* Configure the master mode for TIM2*/
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig);

  /* Configure the output channel generated by TIM2*/
  sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);


  /* Start the timers */
  HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_2);
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1);
  HAL_TIM_OC_Start(&htim2, TIM_CHANNEL_1);
 /* Declaration of the tim handle */
 hal_tim_handle_t htim, htim2;
 hal_tim_config_t tim_config;
 hal_tim_oc_compare_unit_config_t tim_oc_compare_unit_config;
 hal_tim_oc_channel_config_t tim_oc_channel_config;
 hal_tim_slave_config_t slave_config;
 hal_tim_ic_capture_unit_config_t ic_compare_unit_config;
 hal_tim_ic_channel_config_t ic_config;


  /* Ensure that all required peripherals
  (TIM(basic configurations),
   GPIO etc.) are configured properly
   before starting the timers using STM32CubeMX2 */
  .............
 .............

/* Configure the CH2 used to capture the external trigger*/
 ic_config.source    = HAL_TIM_INPUT_TIM1_TI2_GPIO;
 ic_config.polarity  = HAL_TIM_IC_RISING;
 ic_config.filter    = HAL_TIM_FDIV1;
 HAL_TIM_IC_SetConfigChannel(&htim1, HAL_TIM_CHANNEL_2, &ic_config);

 ic_compare_unit_config.source     = HAL_TIM_IC_DIRECT;
 ic_compare_unit_config.prescaler  = HAL_TIM_IC_DIV1;
 HAL_TIM_IC_SetConfigCaptureUnit(&htim1, HAL_TIM_IC_CAPTURE_UNIT_2,
                                 &ic_compare_unit_config);

 /* Configure the slave mode for TIM1*/
 slave_config.mode     = HAL_TIM_SLAVE_GATED;
 slave_config.trigger  = HAL_TIM_TRIG_TI2FP2;
 HAL_TIM_SetSynchroSlave(&htim1, &slave_config);

 /* Configure Master mode */
 HAL_TIM_SetTriggerOutput(&htim1, HAL_TIM_TRGO_ENABLE);
 HAL_TIM_EnableMasterSlaveMode(&htim1);

 /* Configure the output channel generated by TIM1 to trigger TIM2*/
 tim_oc_channel_config.polarity = HAL_TIM_OC_LOW;
 tim_oc_channel_config.idle_state = HAL_TIM_OC_IDLE_STATE_RESET;
 HAL_TIM_OC_SetConfigChannel(&htim1, HAL_TIM_CHANNEL_1,
                             &tim_oc_channel_config);

 tim_oc_compare_unit_config.mode = HAL_TIM_OC_PWM1;
 tim_oc_compare_unit_config.pulse = PULSE_VALUE;
 HAL_TIM_OC_SetConfigCompareUnit(&htim1, HAL_TIM_OC_COMPARE_UNIT_1,
                                 &tim_oc_compare_unit_config);

 /* Configure the slave mode for TIM2*/
 slave_config.mode     = HAL_TIM_SLAVE_GATED;
 slave_config.trigger  = HAL_TIM_TRIG_ITR2;
 HAL_TIM_SetSynchroSlave(&htim2, &slave_config);

 /* Configure the output channel generated by TIM2*/
 tim_oc_channel_config.polarity = HAL_TIM_OC_LOW;
 tim_oc_channel_config.idle_state = HAL_TIM_OC_IDLE_STATE_RESET;
 HAL_TIM_OC_SetConfigChannel(&htim2, HAL_TIM_CHANNEL_1,
                             &tim_oc_channel_config);

 tim_oc_compare_unit_config.mode = HAL_TIM_OC_PWM1;
 tim_oc_compare_unit_config.pulse = PULSE_VALUE;
 HAL_TIM_OC_SetConfigCompareUnit(&htim2, HAL_TIM_OC_COMPARE_UNIT_1,
                                 &tim_oc_compare_unit_config);

 /* Start the timers */
 HAL_TIM_IC_StartChannel(&htim1, HAL_TIM_CHANNEL_2);
 HAL_TIM_OC_StartChannel(&htim1, HAL_TIM_CHANNEL_1);
 HAL_TIM_OC_StartChannel(&htim2, HAL_TIM_CHANNEL_1);
 HAL_TIM_Start(&htim1);
 HAL_TIM_Start(&htim2);

Key changes

  1. HAL2 uses dedicated configuration APIs for slave synchronization, master mode, and output channel configuration.

  2. Timer start in HAL2 uses per-channel start APIs and requires explicit timer start using HAL_TIM_Start().